#include "gType.h"

gType::gType(lexical::token::symbols sym):
	symbol(sym){}
	
gType *gType::copy() const{

	return new gType(*this);

}

gType &gType::operator=(const gType &type){
	
	symbol = type.symbol;
	return *this;
	
}
	
lexical::token::symbols gType::getSymbol() const{

	return symbol;


}

gTypeGo::gTypeGo(unsigned type, float x, float y, float z):
	gType(lexical::token::GO_G), typeValue(type){

	xyzCoordinates[0] = x;
	xyzCoordinates[1] = y;
	xyzCoordinates[2] = z;

}
	
unsigned gTypeGo::getTypeValue() const{

	return typeValue;

}

float &gTypeGo::operator[](unsigned i){

	return xyzCoordinates[i];
	
}

gType *gTypeGo::copy() const{

	return new gTypeGo(*this);

}

gType &gTypeGo::operator=(const gType &type){
	
	const gTypeGo &go = dynamic_cast<const gTypeGo &>(type);
	
	gType::operator=(type);
	typeValue = go.typeValue;
	xyzCoordinates[0] = go.xyzCoordinates[0];
	xyzCoordinates[1] = go.xyzCoordinates[1];
	xyzCoordinates[2] = go.xyzCoordinates[2];
	return *this;
	
}

gTypeGoCircle::gTypeGoCircle(unsigned type, float x, float y, float z, float i, float j, float k):
	gTypeGo(type, x, y, z){

	ijkCoordinates[0] = i;
	ijkCoordinates[1] = j;
	ijkCoordinates[2] = k;

}
	
float &gTypeGoCircle::operator[](unsigned i){

	return  i < 3 ? gTypeGo::operator[](i): ijkCoordinates[i - 3];

}

gType *gTypeGoCircle::copy() const{

	return new gTypeGoCircle(*this);

}

gType &gTypeGoCircle::operator=(const gType &type){
	
	const gTypeGoCircle &circle = dynamic_cast<const gTypeGoCircle &>(type);
	
	gTypeGo::operator=(type);
	ijkCoordinates[0] = circle.ijkCoordinates[0];
	ijkCoordinates[1] = circle.ijkCoordinates[1];
	ijkCoordinates[2] = circle.ijkCoordinates[2];
	return *this;
	
}

gObject::gObject(){

	forceRelative = false;
        alter = false;

}

gObject::~gObject(){

	iterator iter = begin();
	
	//for(; iter != end(); iter++)
		//delete *iter;

}

gObject::gObject(gObject *object){
	
	iterator iter = object->begin();
	
	for(; iter != object->end(); iter++)
		push_back((*iter)->copy());
	
}

bool gObject::isRelative() const{

	return relative;

}

void gObject::setRelative(bool boolean){

	relative = boolean;

}

float gObject::getFeed() const{

	return feed;

}

void gObject::setFeed(float fee){

	feed = fee;

}

int gObject::getSpindle() const{

	return spindle;

}

void gObject::setSpindle(int spin){

	spindle = spin;

}

void gObject::setOffsets(unsigned long start, unsigned long len){

	startOffset = start;
	length = len;

}

unsigned long gObject::getStartOffset() const{

	return startOffset;

}

unsigned long gObject::getLength() const{

	return length;

}

void gObject::setName(std::string &str){

	name = str;

}

std::string &gObject::getName(){

	return name;

}

gObject gObject::getHight(gTypeGo &go){

	gObject object;
	iterator iter = begin();
	
	object.setSpindle(getSpindle());
	object.setFeed(getFeed());
	object.setName(getName());
	for(; iter != end(); iter++){
		if((*iter)->getSymbol() == lexical::token::GO_G){
			gTypeGo &g = dynamic_cast<gTypeGo &>(**iter);
			if(g.getTypeValue() == TYPE_LINEAR_MOVE ||
				g.getTypeValue() == TYPE_LINEAR_CUT ||
				g.getTypeValue() == TYPE_ARC_CLOCK ||
				g.getTypeValue() == TYPE_ARC_COUNTER)
				if(g[0] - GAP < go[0] && g[0] + GAP > go[0] &&
					g[1] - GAP < go[1] && g[1] + GAP > go[1])
					object.push_back(&g);
		}
	}
	return object;

}

int gObject::getIndexByObject(gType *type) const{

	unsigned i;
	
	for(i = 0; i < size(); i++)
		if(type == at(i))
			return i;
	return -1;

}

float *gObject::getRectangle(float *rec){

	gObject::iterator iter = begin();
    gTypeGo *go, *prev;
	
    go = dynamic_cast<gTypeGo *>(*iter);
    rec[0] = rec[2] = (*go)[0];
    rec[1] = rec[3] = (*go)[1];
    iter++;
	while(iter != end()){
		go = dynamic_cast<gTypeGo *>(*iter);
		if((*go)[0] < rec[0])
			rec[0] = (*go)[0];
        if((*go)[0] > rec[2])
			rec[2] = (*go)[0];
		if((*go)[1] < rec[3])
			rec[3] = (*go)[1];
        if((*go)[1] > rec[1])
            rec[1] = (*go)[1];
		if(go->getTypeValue() == TYPE_ARC_CLOCK ||  
			go->getTypeValue() == TYPE_ARC_COUNTER){

            prev = dynamic_cast<gTypeGo *>(*(iter - 1));

            if((*prev)[0] + (*go)[3] < rec[0])
                rec[0] = (*prev)[0] + (*go)[3];
            if((*prev)[0] + (*go)[3] > rec[2])
                rec[2] = (*prev)[0] + (*go)[3];
            if((*prev)[1] + (*go)[4] < rec[3])
                rec[3] = (*prev)[1] + (*go)[4];
            if((*prev)[1] + (*go)[4] > rec[1])
                rec[1] = (*prev)[1] + (*go)[4];
		}
		iter++;
	}
	return rec;

}

gObject &gObject::operator=(const gObject &object){

	unsigned i;
	
	for(i = 0; i < size(); i++)
		*this->at(i) = *object[i];
	return *this;

}

gObjectContainer::gObjectContainer(){}

gObjectContainer::~gObjectContainer(){

	iterator iter = begin();
	
	//for(; iter != end(); iter++)
		//delete *iter;

}

gObjectContainer::gObjectContainer(gObjectContainer *container){
	
	iterator iter = container->begin();
	
	for(; iter != container->end(); iter++)
		push_back(new gObject(*iter));

}

gObject *gObjectContainer::getObjectByName(std::string &str){

	iterator iter = begin();
	
	for(; iter != end(); iter++)
		if(str == (*iter)->getName())
			return *iter;
	return NULL;
	
}

float *gObjectContainer::getRectangle(float *rec){

	iterator iter = begin();
	float buff[4];
	
    (*iter)->getRectangle(buff);
    rec[1] = buff[1];
    rec[2] = buff[2];
    rec[0] = buff[0];
    rec[3] = buff[3];
    iter++;
	while(iter != end()){
		(*iter)->getRectangle(buff);
		if(buff[0] < rec[0])
			rec[0] = buff[0];
		if(buff[3] < rec[3])
			rec[3] = buff[3];
		if(buff[2] > rec[2])
			rec[2] = buff[2];
		if(buff[1] > rec[1])
			rec[1] = buff[1];
		iter++;
	}
	return rec;

}

int gObjectContainer::getIndexByObject(gObject *object) const{

	unsigned i;
	
	for(i = 0; i < size(); i++)
		if(object == at(i))
			return i;
	return -1;

}

gObjectContainer &gObjectContainer::operator=(const gObjectContainer &container){

	unsigned i;
	
	for(i = 0; i < size(); i++)
		*this->at(i) = *container[i];
	return *this;

}

gObjectContainer gObjectContainer::getHight(gTypeGo &go){

	gObjectContainer container;
	iterator iter = begin();
	
	for(; iter != end(); iter++)
		container.push_back(new gObject((*iter)->getHight(go)));
	return container;

}
